import { StructuredNode, NodeType, RawResponseNode, SuggestedQuestionsNode, ToolUseNode, AgentMemoryNode, ThinkingNode, MainTextFinishedNode, ToolUseStartNode } from './types';

/**
 * Node builder helpers for creating structured nodes
 */
export const NodeBuilder = {
  rawResponse(requestId: string, text: string): RawResponseNode {
    return {
      type: NodeType.RawResponse,
      ts: Date.now(),
      requestId,
      text
    };
  },

  thinking(requestId: string, text?: string): ThinkingNode {
    return {
      type: NodeType.Thinking,
      ts: Date.now(),
      requestId,
      text
    };
  },

  toolUseStart(requestId: string, tool: string, input: unknown): ToolUseStartNode {
    return {
      type: NodeType.ToolUseStart,
      ts: Date.now(),
      requestId,
      tool,
      input
    };
  },

  toolUse(requestId: string, tool: string, input: unknown, result?: unknown, error?: string): ToolUseNode {
    return {
      type: NodeType.ToolUse,
      ts: Date.now(),
      requestId,
      tool,
      input,
      result,
      error
    };
  },

  agentMemory(requestId: string, memoryId: string, content: string): AgentMemoryNode {
    return {
      type: NodeType.AgentMemory,
      ts: Date.now(),
      requestId,
      memoryId,
      content
    };
  },

  suggestedQuestions(requestId: string, questions: string[]): SuggestedQuestionsNode {
    return {
      type: NodeType.SuggestedQuestions,
      ts: Date.now(),
      requestId,
      questions
    };
  },

  mainTextFinished(requestId: string): MainTextFinishedNode {
    return {
      type: NodeType.MainTextFinished,
      ts: Date.now(),
      requestId
    };
  }
};

/**
 * Node validation helpers
 */
export const NodeValidator = {
  isValidNode(node: any): node is StructuredNode {
    return node && 
           typeof node.type === 'string' && 
           Object.values(NodeType).includes(node.type) &&
           typeof node.ts === 'number' &&
           typeof node.requestId === 'string';
  },

  isRawResponse(node: StructuredNode): node is RawResponseNode {
    return node.type === NodeType.RawResponse && typeof (node as any).text === 'string';
  },

  isToolUse(node: StructuredNode): node is ToolUseNode {
    return node.type === NodeType.ToolUse && 
           typeof (node as any).tool === 'string' &&
           (node as any).input !== undefined;
  },

  isAgentMemory(node: StructuredNode): node is AgentMemoryNode {
    return node.type === NodeType.AgentMemory &&
           typeof (node as any).memoryId === 'string' &&
           typeof (node as any).content === 'string';
  }
};

/**
 * Text aggregation utilities
 */
export const TextAggregator = {
  /**
   * Combine all RAW_RESPONSE nodes into a single text string
   */
  aggregateRawText(nodes: StructuredNode[]): string {
    return nodes
      .filter(NodeValidator.isRawResponse)
      .map(node => node.text)
      .join('');
  },

  /**
   * Get the thinking text if any
   */
  getThinkingText(nodes: StructuredNode[]): string {
    const thinkingNodes = nodes.filter(n => n.type === NodeType.Thinking);
    return thinkingNodes.map(n => (n as ThinkingNode).text || '').join(' ');
  },

  /**
   * Extract all suggested questions
   */
  extractSuggestedQuestions(nodes: StructuredNode[]): string[] {
    const suggestedNode = nodes.find(n => n.type === NodeType.SuggestedQuestions) as SuggestedQuestionsNode;
    return suggestedNode?.questions || [];
  }
};

/**
 * Turn analysis utilities
 */
export const TurnAnalyzer = {
  /**
   * Check if turn is complete (has MAIN_TEXT_FINISHED)
   */
  isComplete(nodes: StructuredNode[]): boolean {
    return nodes.some(n => n.type === NodeType.MainTextFinished);
  },

  /**
   * Count nodes by type
   */
  getNodeCounts(nodes: StructuredNode[]): Record<NodeType, number> {
    const counts = Object.values(NodeType).reduce((acc, type) => {
      acc[type] = 0;
      return acc;
    }, {} as Record<NodeType, number>);

    nodes.forEach(node => {
      counts[node.type]++;
    });

    return counts;
  },

  /**
   * Get turn summary statistics
   */
  getSummary(nodes: StructuredNode[]): {
    isComplete: boolean;
    textLength: number;
    toolsUsed: number;
    memoriesCreated: number;
    suggestedQuestions: number;
    hasThinking: boolean;
  } {
    const counts = this.getNodeCounts(nodes);
    const fullText = TextAggregator.aggregateRawText(nodes);
    
    return {
      isComplete: this.isComplete(nodes),
      textLength: fullText.length,
      toolsUsed: counts[NodeType.ToolUse],
      memoriesCreated: counts[NodeType.AgentMemory],
      suggestedQuestions: TextAggregator.extractSuggestedQuestions(nodes).length,
      hasThinking: counts[NodeType.Thinking] > 0
    };
  }
};
